package com.pactera.madp.cp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.cp.api.dto.channel.*;
import com.pactera.madp.cp.api.dto.channel.channelcodeadddtos.EmployeeAddUpperLimitList;
import com.pactera.madp.cp.api.dto.channel.channelcodeadddtos.EmployeeIdList;
import com.pactera.madp.cp.api.dto.channel.channelcodeadddtos.EmployeeTopBottomLineLists;
import com.pactera.madp.cp.api.em.channel.ChannelCodeStatusEnum;
import com.pactera.madp.cp.api.entity.*;
import com.pactera.madp.cp.api.entity.channel.ChannelCodeContactStatisticsEntity;
import com.pactera.madp.cp.api.entity.channel.ChannelCodeEntity;
import com.pactera.madp.cp.api.entity.channel.ChannelCodeGroupEntity;
import com.pactera.madp.cp.api.entity.wm.WorkMsgEntity;
import com.pactera.madp.cp.api.model.channel.*;
import com.pactera.madp.cp.api.page.SubPage;
import com.pactera.madp.cp.api.vo.channel.*;
import com.pactera.madp.cp.api.vo.channel.channelcodepagevo.ChannelCodeContrastDetailsExcelVO;
import com.pactera.madp.cp.common.util.DateHastListUtil;
import com.pactera.madp.cp.common.util.DateUtils;
import com.pactera.madp.cp.common.util.PageUtil;
import com.pactera.madp.cp.common.util.wm.WorkMsgHelper;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.channel.ChannelCodeContactStatisticsMapper;
import com.pactera.madp.cp.mapper.wm.WorkMsgMapper;
import com.pactera.madp.cp.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.select.Evaluator;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * ChannelCodeContactStatisticsServiceImpl
 *
 * @author jun
 * @version 1.0
 * 2021/8/4 15:10
 **/
@Service
@Slf4j
@AllArgsConstructor
public class ChannelCodeContactStatisticsServiceImpl extends ServiceImpl<ChannelCodeContactStatisticsMapper, ChannelCodeContactStatisticsEntity> implements ChannelCodeContactStatisticsService {

    private  IWorkContactEmployeeService workContactEmployeeService;

    private IChannelCodeService channelCodeService;

    private IWorkEmployeeService employeeService;

    private IWorkContactService workContactService;

    private IWorkContactTagPivotService workContactTagPivotService;

    private IWorkContactTagService workContactTagService;

    private IChannelCodeGroupService channelCodeGroupService;

    private WorkMsgMapper workMsgMapper;

    /**
     * 新增或修改成员添加客户统计信息
     * @param corpId
     */
    /*@Override
    public void saveContact(Integer corpId) {

        //获取所有新增客户，包括删除客户
        List<ChannelCodeAllAddContactData> allContact = baseMapper.getAllAddContact(corpId);
        //获取所有客户
        List<ChannelCodeAllContactData> allAddContact = baseMapper.getAllContact(corpId);
        //获取所有流失客户
        List<ChannelCodeAllLossContactData> allLossContact = baseMapper.getAllLossContact(corpId);
        //获取今日新增客户
        List<ChannelCodeNewAddContactData> newAddContact = baseMapper.getNewAddContact(corpId, DateUtil.beginOfDay(DateUtil.date()).toString(),DateUtil.endOfDay(DateUtil.date()).toString());
        //获取今日流失客户
        List<ChannelCodeNewLossContactData> newLossContact = baseMapper.getNewLossContact(corpId, DateUtil.beginOfDay(DateUtil.date()).toString(), DateUtil.endOfDay(DateUtil.date()).toString());
        //将上面所有数据写入输入对象
        LinkedList<ChannelCodeContactStatisticsAddDTO> dtos = new LinkedList<>();
        allContact.forEach(data -> {
            ChannelCodeContactStatisticsAddDTO dto = new ChannelCodeContactStatisticsAddDTO();
            dto.setAllContact(data.getAllAddContact());
            dto.setNewLossContact(0);
            dto.setAllLossContact(0);
            dto.setNewAddContact(0);
            dto.setAllAddContact(0);
            dto.setEmployeeId(data.getEmployeeId());
            dto.setChannelId(Integer.valueOf(data.getState().split("-")[1]));
            dtos.add(dto);
        });
        dtos.forEach(dto -> {
            for (int i = 0; i < allLossContact.size(); i++) {
                if (dto.getChannelId().equals(Integer.valueOf(allLossContact.get(i).getState().split("-")[1])) && dto.getEmployeeId().equals(allLossContact.get(i).getEmployeeId())){
                    if (allLossContact.get(i).getAllLossContact() != null) {
                        dto.setAllLossContact(allLossContact.get(i).getAllLossContact());
                        break;
                    }
                }
            }

            for (int i = 0; i < allAddContact.size(); i++) {
                if (dto.getChannelId().equals(Integer.valueOf(allAddContact.get(i).getState().split("-")[1])) && dto.getEmployeeId().equals(allAddContact.get(i).getEmployeeId())){
                    if (allAddContact.get(i).getAllContact() != null) {
                        dto.setAllAddContact(allAddContact.get(i).getAllContact());
                        break;
                    }
                }
            }

            for (int i = 0; i < newAddContact.size(); i++) {
                if (dto.getChannelId().equals(Integer.valueOf(newAddContact.get(i).getState().split("-")[1])) && dto.getEmployeeId().equals(newAddContact.get(i).getEmployeeId())){
                    if (newAddContact.get(i).getNewAddContact() != null) {
                        dto.setNewAddContact(newAddContact.get(i).getNewAddContact());
                        break;
                    }
                }
            }

            for (int i = 0; i < newLossContact.size(); i++) {
                if (dto.getChannelId().equals(Integer.valueOf(newLossContact.get(i).getState().split("-")[1])) && dto.getEmployeeId().equals(newLossContact.get(i).getEmployeeId())){
                    if (newLossContact.get(i).getNewLossContact() != null) {
                        dto.setNewLossContact(newLossContact.get(i).getNewLossContact());
                        break;
                    }
                }
            }
        });

        List<ChannelCodeEntity> channelCodeEntities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                .eq(ChannelCodeEntity::getCorpId, corpId));
        channelCodeEntities.forEach(cc -> {
            // 如果该渠道 客服人员状态为1-全天在线
            if (cc.getCustomerServicePersonnelStatus().equals(1)) {
                List<Integer> empIdss = new LinkedList<>();
                // 获取全天在线员工列表
                List<EmployeeIdList> empIds = JSONArray.parseArray(cc.getEmployeeAllDayLongList(), EmployeeIdList.class);
                empIds.forEach(e -> {
                    empIdss.add(e.getId());
                });

                // 判断是否有备用员工，如果有则添加

                // 如果员工添加上限状态为1-开启
                if (cc.getEmployeeAddUpperLimitStatus().equals(1)) {
                    // 获取员工每日添加客户上限列表
                    List<EmployeeAddUpperLimitList> lists = JSONArray.parseArray(cc.getEmployeeAddUpperLimitList(), EmployeeAddUpperLimitList.class);
                    lists.forEach(l -> {
                        empIdss.add(l.getEmployeeId());
                    });
                }
                List<Integer> collect = empIdss.stream().distinct().collect(Collectors.toList());
                List<ChannelCodeContactStatisticsEntity> list = list(
                        Wrappers.<ChannelCodeContactStatisticsEntity>lambdaQuery()
                        .eq(BaseEntity::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).toString())
                        .eq(ChannelCodeContactStatisticsEntity::getCorpId, corpId)
                        .eq(ChannelCodeContactStatisticsEntity::getChannelId, cc.getId())
                );
                if (list.isEmpty()) {
                    List<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
                    collect.forEach(e -> {
                        ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
                        entity.setChannelId(cc.getId());
                        entity.setEmployeeId(e);
                        entity.setCorpId(corpId);
                        entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
                        AtomicBoolean flag = new AtomicBoolean(true);
                        dtos.forEach(d -> {
                            if (entity.getChannelId().equals(d.getChannelId()) && entity.getEmployeeId().equals(d.getEmployeeId())) {
                                BeanUtil.copyProperties(d, entity);
                                flag.set(false);
                            }
                        });
                        if (flag.get()) {
                            entity.setAllAddContact(0);
                            entity.setNewAddContact(0);
                            entity.setAllLossContact(0);
                            entity.setNewLossContact(0);
                            entity.setAllContact(0);
                        }
                        entities.add(entity);
                    });
                    saveBatch(entities);
                } else {
                    List<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
                    collect.forEach(e -> {
                        ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
                        AtomicBoolean flag = new AtomicBoolean(true);
                        list.forEach(l -> {
                            if (l.getEmployeeId().equals(e)) {
                                BeanUtil.copyProperties(l, entity);
                                flag.set(false);
                                dtos.forEach(d -> {
                                    if (l.getChannelId().equals(d.getChannelId()) && l.getEmployeeId().equals(d.getEmployeeId())){
                                        BeanUtil.copyProperties(d, entity);
                                        flag.set(false);
                                    }
                                });
                            }
                        });

                        if (flag.get()) {
                            entity.setChannelId(cc.getId());
                            entity.setEmployeeId(e);
                            entity.setCorpId(corpId);
                            entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
                            entity.setAllAddContact(0);
                            entity.setNewAddContact(0);
                            entity.setAllLossContact(0);
                            entity.setNewLossContact(0);
                            entity.setAllContact(0);
                        }
                        entities.add(entity);
                    });
                    saveOrUpdateBatch(entities);
                }
            } else {
                // 否则该渠道 客服人员状态为2-自动上下线
                List<ChannelCodeContactStatisticsEntity> list = list(Wrappers.<ChannelCodeContactStatisticsEntity>lambdaQuery()
                        .eq(BaseEntity::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).toString())
                        .eq(ChannelCodeContactStatisticsEntity::getCorpId, corpId)
                        .eq(ChannelCodeContactStatisticsEntity::getChannelId, cc.getId()));
                List<EmployeeTopBottomLineLists> topBottomLineLists = JSONArray.parseArray(cc.getEmployeeTopBottomLineList(), EmployeeTopBottomLineLists.class);
                List<Integer> empIdss = new LinkedList<>();
                topBottomLineLists.forEach(top -> {
                    top.getEmployeeIdList().forEach(em -> {
                        empIdss.add(em.getId());
                    });
                });
                //判断是否有备用员工，如果有则添加
                if (cc.getEmployeeAddUpperLimitStatus().equals(1)) {
                    List<EmployeeAddUpperLimitList> lists = JSONArray.parseArray(cc.getEmployeeAddUpperLimitList(), EmployeeAddUpperLimitList.class);
                    lists.forEach(l -> {
                        empIdss.add(l.getEmployeeId());
                    });
                }
                List<Integer> collect = empIdss.stream().distinct().collect(Collectors.toList());
                if (list.isEmpty()){
                    LinkedList<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
                    collect.forEach(e -> {
                        ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
                        entity.setChannelId(cc.getId());
                        entity.setEmployeeId(e);
                        entity.setCorpId(corpId);
                        entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
                        AtomicBoolean flag = new AtomicBoolean(true);
                        dtos.forEach(d -> {
                            if (entity.getChannelId().equals(d.getChannelId()) && entity.getEmployeeId().equals(d.getEmployeeId())){
                                BeanUtil.copyProperties(d, entity);
                                flag.set(false);
                            }
                        });
                        if (flag.get()) {
                            entity.setAllAddContact(0);
                            entity.setNewAddContact(0);
                            entity.setAllLossContact(0);
                            entity.setNewLossContact(0);
                            entity.setAllContact(0);
                        }
                        entities.add(entity);
                    });
                    saveBatch(entities);
                } else {
                    List<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
                    collect.forEach(e -> {
                        ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
                        AtomicBoolean flag = new AtomicBoolean(true);
                        list.forEach(l -> {
                            if (l.getEmployeeId().equals(e)) {
                                BeanUtil.copyProperties(l, entity);
                                flag.set(false);
                                dtos.forEach(d -> {
                                    if (l.getChannelId().equals(d.getChannelId()) && l.getEmployeeId().equals(d.getEmployeeId())){
                                        BeanUtil.copyProperties(d, entity);
                                        flag.set(false);
                                    }
                                });
                            }
                        });

                        if (flag.get()){
                            entity.setChannelId(cc.getId());
                            entity.setEmployeeId(e);
                            entity.setCorpId(corpId);
                            entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
                            entity.setAllAddContact(0);
                            entity.setNewAddContact(0);
                            entity.setAllLossContact(0);
                            entity.setNewLossContact(0);
                            entity.setAllContact(0);
                        }
                        entities.add(entity);
                    });
                    saveOrUpdateBatch(entities);
                }
            }
        });
    }*/
//    @Override
//    public void saveContact(Integer corpId) {
//        LinkedList<ChannelCodeContactStatisticsAddDTO> dtos = baseData(corpId);
//        LinkedList<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
//        List<ChannelCodeEntity> channelCodeEntities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
//                .eq(ChannelCodeEntity::getCorpId, corpId));
//        channelCodeEntities.forEach(cc -> {
//            List<Integer> empIdss = new LinkedList<>();
//            // 如果该渠道 客服人员状态为1-全天在线
//            if (cc.getCustomerServicePersonnelStatus().equals(1)) {
//                // 获取全天在线员工列表
//                List<EmployeeIdList> empIds = JSONArray.parseArray(cc.getEmployeeAllDayLongList(), EmployeeIdList.class);
//                empIds.forEach(e -> {
//                    empIdss.add(e.getId());
//                });
//            } else {
//                // 否则该渠道 客服人员状态为2-自动上下线
//                List<EmployeeTopBottomLineLists> topBottomLineLists = JSONArray.parseArray(cc.getEmployeeTopBottomLineList(), EmployeeTopBottomLineLists.class);
//                topBottomLineLists.forEach(top -> {
//                    top.getEmployeeIdList().forEach(em -> {
//                        empIdss.add(em.getId());
//                    });
//                });
//            }
//            postHandle(empIdss, cc, corpId, dtos, entities);
//        });
//        saveOrUpdateBatch(entities);
//    }
    @Override
    public void saveContact(Integer corpId) {
        LinkedList<ChannelCodeContactStatisticsAddDTO> dtos = baseData(corpId);
        LinkedList<ChannelCodeContactStatisticsEntity> entities = new LinkedList<>();
        // 查询渠道活码所有渠道
        List<ChannelCodeEntity> channelCodeEntities = channelCodeService.list(
                Wrappers.<ChannelCodeEntity>lambdaQuery()
                        .eq(ChannelCodeEntity::getCorpId, corpId)
                .eq(ChannelCodeEntity::getDelFlag, 0)
        );
        // 查询当前（当天）所有按channelId-employeeId维度的统计数据
        List<ChannelCodeContactStatisticsEntity> statistics = list(Wrappers.<ChannelCodeContactStatisticsEntity>lambdaQuery()
                .eq(BaseEntity::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).toString())
                .eq(ChannelCodeContactStatisticsEntity::getCorpId, corpId));
        // 遍历渠道
        channelCodeEntities.forEach(cc -> {
            // 获取该渠道客服人员（（全天在线 或 自动上下线） 与 备用员工）
            List<Integer> empIds = getEmpIdss(cc);
            // 获取当前（当天）当前渠道所有按employeeId维度的统计数据
            List<ChannelCodeContactStatisticsEntity> list = statistics.stream()
                    .filter(s -> cc.getId().equals(s.getChannelId()))
                    .collect(Collectors.toList());
            if (list.isEmpty()) {
                handleEmptyList(empIds, cc, corpId, dtos, entities);
            } else {
                hadleNotEmptyList(list, empIds, cc, corpId, dtos, entities);
            }
        });
        saveOrUpdateBatch(entities);
    }
    private List<Integer> getEmpIdss(ChannelCodeEntity channelCodeEntity) {
        List<Integer> empIdss = new LinkedList<>();
        // 如果该渠道 客服人员状态为1-全天在线
        if (channelCodeEntity.getCustomerServicePersonnelStatus().equals(1)) {
            // 获取全天在线员工列表
            List<EmployeeIdList> empIds = JSONArray.parseArray(channelCodeEntity.getEmployeeAllDayLongList(), EmployeeIdList.class);
            empIds.forEach(e -> {
                empIdss.add(e.getId());
            });
        } else {
            // 否则该渠道 客服人员状态为2-自动上下线
            List<EmployeeTopBottomLineLists> topBottomLineLists = JSONArray.parseArray(channelCodeEntity.getEmployeeTopBottomLineList(), EmployeeTopBottomLineLists.class);
            topBottomLineLists.forEach(top -> {
                top.getEmployeeIdList().forEach(em -> {
                    empIdss.add(em.getId());
                });
            });
        }
        //判断是否有备用员工，如果有则添加
        if (channelCodeEntity.getEmployeeAddUpperLimitStatus().equals(1)) {
            List<EmployeeAddUpperLimitList> lists = JSONArray.parseArray(channelCodeEntity.getEmployeeAddUpperLimitList(), EmployeeAddUpperLimitList.class);
            lists.forEach(l -> {
                empIdss.add(l.getEmployeeId());
            });
        }
        return empIdss.stream().distinct().collect(Collectors.toList());
    }
    private LinkedList<ChannelCodeContactStatisticsAddDTO> baseData(Integer corpId) {
        //获取所有新增客户，包括删除客户
        List<ChannelCodeAllAddContactData> allContact = baseMapper.getAllAddContact(corpId);
        //获取所有客户
        List<ChannelCodeAllContactData> allAddContact = baseMapper.getAllContact(corpId);
        //获取所有流失客户
        List<ChannelCodeAllLossContactData> allLossContact = baseMapper.getAllLossContact(corpId);
        //获取今日新增客户
        List<ChannelCodeNewAddContactData> newAddContact = baseMapper.getNewAddContact(corpId, DateUtil.beginOfDay(DateUtil.date()).toString(), DateUtil.endOfDay(DateUtil.date()).toString());
        //获取今日流失客户
        List<ChannelCodeNewLossContactData> newLossContact = baseMapper.getNewLossContact(corpId, DateUtil.beginOfDay(DateUtil.date()).toString(), DateUtil.endOfDay(DateUtil.date()).toString());
        //将上面所有数据写入输入对象
        LinkedList<ChannelCodeContactStatisticsAddDTO> dtos = new LinkedList<>();
        allContact.forEach(data -> {
            ChannelCodeContactStatisticsAddDTO dto = new ChannelCodeContactStatisticsAddDTO();
            dto.setAllContact(data.getAllAddContact());
            dto.setNewLossContact(0);
            dto.setAllLossContact(0);
            dto.setNewAddContact(0);
            dto.setAllAddContact(0);
            for (int i = 0; i < allLossContact.size(); i++) {
                if (data.getState().equals(allLossContact.get(i).getState()) && data.getEmployeeId().equals(allLossContact.get(i).getEmployeeId())) {
                    if (allLossContact.get(i).getAllLossContact() != null) {
                        dto.setAllLossContact(allLossContact.get(i).getAllLossContact());
                        break;
                    }
                }
            }
            for (int i = 0; i < allAddContact.size(); i++) {
                if (data.getState().equals(allAddContact.get(i).getState()) && data.getEmployeeId().equals(allAddContact.get(i).getEmployeeId())) {
                    if (allAddContact.get(i).getAllContact() != null) {
                        dto.setAllAddContact(allAddContact.get(i).getAllContact());
                        break;
                    }
                }
            }
            for (int i = 0; i < newAddContact.size(); i++) {
                if (data.getState().equals(newAddContact.get(i).getState()) && data.getEmployeeId().equals(newAddContact.get(i).getEmployeeId())) {
                    if (newAddContact.get(i).getNewAddContact() != null) {
                        dto.setNewAddContact(newAddContact.get(i).getNewAddContact());
                        break;
                    }
                }
            }
            for (int i = 0; i < newLossContact.size(); i++) {
                if (data.getState().equals(newLossContact.get(i).getState()) && data.getEmployeeId().equals(newLossContact.get(i).getEmployeeId())) {
                    if (newLossContact.get(i).getNewLossContact() != null) {
                        dto.setNewLossContact(newLossContact.get(i).getNewLossContact());
                        break;
                    }
                }
            }

            dto.setEmployeeId(data.getEmployeeId());
            dto.setChannelId(Integer.valueOf(data.getState().split("-")[1]));
            dtos.add(dto);
        });
        return dtos;
    }
    private void handleEmptyList(
            List<Integer> empIds,
            ChannelCodeEntity cc,
            Integer corpId,
            LinkedList<ChannelCodeContactStatisticsAddDTO> dtos,
            LinkedList<ChannelCodeContactStatisticsEntity> entities
    ) {
        empIds.forEach(empId -> {
            ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
            entity.setChannelId(cc.getId());
            entity.setEmployeeId(empId);
            entity.setCorpId(corpId);
            entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
            AtomicBoolean flag = new AtomicBoolean(true);
            dtos.forEach(d -> {
                if (entity.getChannelId().equals(d.getChannelId()) && entity.getEmployeeId().equals(d.getEmployeeId())) {
                    BeanUtil.copyProperties(d, entity);
                    flag.set(false);
                }
            });
            if (flag.get()) {
                entity.setAllAddContact(0);
                entity.setNewAddContact(0);
                entity.setAllLossContact(0);
                entity.setNewLossContact(0);
                entity.setAllContact(0);
            }
            entities.add(entity);
        });
    }
    private void hadleNotEmptyList(
            List<ChannelCodeContactStatisticsEntity> list,
            List<Integer> empIds,
            ChannelCodeEntity cc,
            Integer corpId,
            LinkedList<ChannelCodeContactStatisticsAddDTO> dtos,
            LinkedList<ChannelCodeContactStatisticsEntity> entities
    ) {
        empIds.forEach(empId -> {
            ChannelCodeContactStatisticsEntity entity = new ChannelCodeContactStatisticsEntity();
            AtomicBoolean flag = new AtomicBoolean(true);
            list.forEach(l -> {
                if (l.getEmployeeId().equals(empId)) {
                    BeanUtil.copyProperties(l, entity);
                    flag.set(false);
                    dtos.forEach(d -> {
                        if (l.getChannelId().equals(d.getChannelId()) && l.getEmployeeId().equals(d.getEmployeeId())){
                            BeanUtil.copyProperties(d, entity);
                            flag.set(false);
                        }
                    });
                }
            });

            if (flag.get()) {
                entity.setChannelId(cc.getId());
                entity.setEmployeeId(empId);
                entity.setCorpId(corpId);
                entity.setCreateTime(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date())));
                entity.setAllAddContact(0);
                entity.setNewAddContact(0);
                entity.setAllLossContact(0);
                entity.setNewLossContact(0);
                entity.setAllContact(0);
            }
            entities.add(entity);
        });
    }
    /**
     * 渠道活码基础信息
     * @param dto
     * @return
     */
    @Override
    public ChannelCodeContactDetailsVO channelCodeDetails(ChannelCodeContrastDetailsDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());
        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",DateUtil.beginOfDay(DateUtil.date()));
        wrapper.le("create_time",DateUtil.endOfDay(DateUtil.date()));
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        wrapper.in("channel_id",channelId);
        Map<String, Object> maps = this.getMap(wrapper);

        ChannelCodeContactDetailsVO vo = new ChannelCodeContactDetailsVO();
        vo.setChannelId(channelId);
        vo.setNewAddContact(Integer.parseInt(maps.get("newAddContact") == null ? "0" : maps.get("newAddContact").toString()));
        vo.setAllAddContact(Integer.parseInt(maps.get("allAddContact") == null ? "0" : maps.get("allAddContact").toString()));
        vo.setAllLossContact(Integer.parseInt(maps.get("allLossContact") == null ? "0" : maps.get("allLossContact").toString()));
        vo.setNewLossContact(Integer.parseInt(maps.get("newLossContact") == null ? "0" : maps.get("newLossContact").toString()));
        return vo;
    }

    /**
     * 渠道活码图表数据折线图
     * @param dto
     * @return
     */
    @Override
    public List<ChannelCodeChartDataVO> getChannelCodeChartDate(ChannelCodeChartDataDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());
        List<DateTime> list = DateHastListUtil.getDetHashList(dto.getStartTime(), dto.getEndTime());

        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("create_time,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
        wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        wrapper.in("channel_id",channelId);
        if (dto.getEmployeeId() != null){
            wrapper.eq("employee_id",dto.getEmployeeId());
        }
        wrapper.groupBy("create_time");
        List<Map<String, Object>> maps = this.listMaps(wrapper);
        List<ChannelCodeChartDataVO> vos = new LinkedList<>();

        list.forEach(l->{
            ChannelCodeChartDataVO vo = new ChannelCodeChartDataVO();
            vo.setType(dto.getType());
            vo.setCreateTime(DateUtil.formatDate(l));
            vo.setCounts(0);
            maps.forEach(m->{
                DateTime createTime = DateTime.of(m.get("create_time").toString(), "yyyy-MM-dd");
                if (createTime.getTime() == l.getTime()){
                    switch (dto.getType()){
                        case 2:
                            vo.setCounts(Integer.valueOf(m.get("newAddContact").toString()));
                            break;
                        case 3:
                            vo.setCounts(Integer.valueOf(m.get("newLossContact").toString()));
                            break;
                        default:
                            vo.setCounts(Integer.valueOf(m.get("allAddContact").toString()));
                    }
                }
            });
            vos.add(vo);
        });

        return vos;
    }

    /**
     * 按日期查看表格-分页
     * @param page
     * @param dto
     * @return
     */
    @Override
    public Page<ChannelCodeTableDateVO> getChannelCodeTableDate(Page page, ChannelCodeTableDateDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());
        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("create_time,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
        wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        if (dto.getEmployeeId()!=null){
            wrapper.eq("employee_id",dto.getEmployeeId());
        }
        wrapper.in("channel_id",channelId);
        wrapper.groupBy("create_time");
        wrapper.orderByDesc("create_time");
        List<Map<String, Object>> maps = listMaps(wrapper);

        List<ChannelCodeTableDateVO> vos = new LinkedList<>();
        List<DateTime> list = DateHastListUtil.getDetHashList(dto.getStartTime(), dto.getEndTime());
        list.forEach(l->{
            ChannelCodeTableDateVO vo = new ChannelCodeTableDateVO();
            vo.setChannelId(dto.getChannelId());
            vo.setCreateTime(DateUtil.formatDate(l));
            vo.setNewAddContact(0);
            vo.setNewLossContact(0);
            vo.setAllAddContact(0);
            maps.forEach(m->{
                DateTime createTime = DateTime.of(m.get("create_time").toString(), "yyyy-MM-dd");
                if (createTime.getTime() == l.getTime()){
                    vo.setNewAddContact(Integer.valueOf(m.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(m.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(m.get("allAddContact").toString()));
                }
            });
            vos.add(vo);
        });

        vos.sort(Comparator.comparing(ChannelCodeTableDateVO::getCreateTime).reversed());
        return PageUtil.split(vos, (int) page.getCurrent(), (int) page.getSize());
    }

    /**
     * 按日期查询表格-查看详情列表
     * @param page
     * @param dto
     * @return
     */
    @Override
    public Page<List<ChannelCodeTableDateDetailsVO>> getChannelCodeTableDateDetails(Page page, ChannelCodeTableDateDetailsDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        List<String> channelIds = new LinkedList<>();
        channelId.forEach(c->{
            channelIds.add("channelCodeId-"+c);
        });
        if (dto.getType().equals(1)){
            QueryWrapper<WorkContactEmployeeEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("corp_id", CorpContextHolder.getCorpId());
            wrapper.in("state",channelIds);
            wrapper.le("create_time",dto.getEndTime() + " 23:59:59");
            if (dto.getEmployeeId() != null){
                wrapper.eq("employee_id",dto.getEmployeeId());
            }
            IPage iPage = workContactEmployeeService.page(page, wrapper);

            List<WorkContactEmployeeEntity> records = iPage.getRecords();
            List<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(vos);
            subPage.setPages(iPage.getPages());
            subPage.setTotal(iPage.getTotal());
            subPage.setCurrent(iPage.getCurrent());
            subPage.setSize(iPage.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else if (dto.getType().equals(2)){
//            QueryWrapper<WorkContactEmployeeEntity> wrapper = new QueryWrapper<>();
//            wrapper.eq("corp_id", CorpContextHolder.getCorpId());
//            wrapper.in("state",channelIds);
//            wrapper.le("create_time",dto.getEndTime() + " 23:59:59");
//            wrapper.ge("create_time",dto.getStartTime() + " 00:00:00");
//            if (dto.getEmployeeId() != null){
//                wrapper.eq("employee_id",dto.getEmployeeId());
//            }
//            IPage iPage = workContactEmployeeService.page(page, wrapper);
            IPage iPage = workContactEmployeeService.myPage(
                    CorpContextHolder.getCorpId(), channelIds, dto.getStartTime() + " 00:00:00",
                    dto.getEndTime() + " 23:59:59", dto.getEmployeeId(), page
            );
            List<WorkContactEmployeeEntity> records = iPage.getRecords();
            LinkedList<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(vos);
            subPage.setPages(iPage.getPages());
            subPage.setTotal(iPage.getTotal());
            subPage.setCurrent(iPage.getCurrent());
            subPage.setSize(iPage.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else if (dto.getType().equals(3)){
            List<WorkContactEmployeeEntity> lossContact = workContactEmployeeService.getAllLossContact(dto.getEndTime() + " 23:59:59", channelIds,dto.getEmployeeId());
            List<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            lossContact.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());


                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });
                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatus(2);
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vos.add(vo);
            });
            List<ChannelCodeTableDateDetailsVO> collect = vos.stream().distinct().collect(Collectors.toList());
            collect.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());

            Page<ChannelCodeTableDateDetailsVO> split = PageUtil.split(collect, (int) page.getCurrent(), (int) page.getSize());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(split.getRecords());
            subPage.setPages(split.getPages());
            subPage.setTotal(split.getTotal());
            subPage.setCurrent(split.getCurrent());
            subPage.setSize(split.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else {
            HashMap<String, Object> map = new HashMap<>();
            SubPage subPage = new SubPage();
            subPage.setExtraProps(map);
            map.put("nowTime",DateTime.now().toDateStr());
            return subPage;
        }
    }

    /**
     * 按日期查询表格-查看详情列表-导出Excel
     * @param response
     * @param out
     * @param dto
     */
    @Override
    public void getChannelCodeTableDateDetailsExcel(HttpServletResponse response, OutputStream out,ChannelCodeTableDateDetailsDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        List<String> channelIds = new LinkedList<>();
        channelId.forEach(c->{
            channelIds.add("channelCodeId-"+c);
        });
        if (dto.getType().equals(1)){
            QueryWrapper<WorkContactEmployeeEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("corp_id", CorpContextHolder.getCorpId());
            wrapper.in("state",channelIds);
            wrapper.le("create_time",dto.getEndTime() + " 23:59:59");
            if (dto.getEmployeeId() != null){
                wrapper.eq("employee_id",dto.getEmployeeId());
            }
            List<WorkContactEmployeeEntity> records = workContactEmployeeService.list(wrapper);
            LinkedList<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(employeeEntity.getStatus()));
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,vos);
        }else if (dto.getType().equals(2)){

            QueryWrapper<WorkContactEmployeeEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("corp_id", CorpContextHolder.getCorpId());
            wrapper.in("state",channelIds);
            wrapper.le("create_time",dto.getEndTime() + " 23:59:59");
            wrapper.ge("create_time",dto.getStartTime() + " 00:00:00");
            if (dto.getEmployeeId() != null){
                wrapper.eq("employee_id",dto.getEmployeeId());
            }
            List<WorkContactEmployeeEntity> records = workContactEmployeeService.list(wrapper);
            LinkedList<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(employeeEntity.getStatus()));
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,vos);
        }else{
            List<WorkContactEmployeeEntity> lossContact = workContactEmployeeService.getAllLossContact(dto.getEndTime() + " 23:59:59", channelIds,dto.getEmployeeId());
            List<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            lossContact.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());


                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(2));
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            List<ChannelCodeTableDateDetailsExcelVO> collect = vos.stream().distinct().collect(Collectors.toList());
            collect.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,collect);
        }
    }

    /**
     * 按日期查询表格-查看详情列表-导出Excel-私有方法
     * @param response
     * @param out
     * @param vos
     */
    private void getChannelCodeTableDateDetailsExcel(HttpServletResponse response, OutputStream out,List<ChannelCodeTableDateDetailsExcelVO> vos){
        ArrayList<ChannelCodeTableDateDetailsExcelVO> rows = CollUtil.newArrayList(vos);
        if (rows.isEmpty()){
            ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
            rows.add(vo);
        }
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);



        //自定义标题别名
        writer.addHeaderAlias("contactName", "客户姓名");
        writer.addHeaderAlias("employeeName", "所属客服");
        writer.addHeaderAlias("customerScoring", "客户评分");
        writer.addHeaderAlias("tagsList", "标签列表");
        writer.addHeaderAlias("status", "客户状态");
        writer.addHeaderAlias("createTime", "添加时间");
        writer.addHeaderAlias("lastTime", "上次对话时间");
        writer.addHeaderAlias("channel", "添加渠道");


        //合并单元格后的标题行，使用默认标题样式
        writer.merge(0, 3,0,7,"客户列表（导出时间"+DateUtil.now()+"）",true);
        //跳过当前行，既第一行，非必须，在此演示用
        writer.passCurrentRow();
        writer.passCurrentRow();
        writer.passCurrentRow();
        writer.passCurrentRow();


        writer.autoSizeColumnAll();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=table-date-datails.xlsx");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }

    /**
     * 按员工查看表格-分页
     * @param page
     * @param dto
     * @return
     */
    @Override
    public Page<List<ChannelCodeTableEmployeeVO>> getChannelCodeTableDateEmployee(Page page, ChannelCodeTableEmployeeDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("employee_id,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
        wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
        if (dto.getEmployeeId() != null){
            wrapper.eq("employee_id",dto.getEmployeeId());
        }
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        wrapper.in("channel_id",channelId);
        wrapper.groupBy("employee_id");
        wrapper.orderByDesc("employee_id");
        Page iPage = (Page) pageMaps(page, wrapper);
        List<Map<String, Object>> records = iPage.getRecords();
        List<ChannelCodeTableEmployeeVO> vos = new LinkedList<>();
        records.forEach(r->{
            ChannelCodeTableEmployeeVO vo = new ChannelCodeTableEmployeeVO();
            WorkEmployeeEntity entity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .eq(WorkEmployeeEntity::getId, r.get("employee_id")));
            QueryWrapper<ChannelCodeContactStatisticsEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("sum(all_add_contact) as allAddContact");
            queryWrapper.ge("create_time",dto.getEndTime()+" 00:00:00");
            queryWrapper.le("create_time",dto.getEndTime()+" 23:59:59");
            queryWrapper.eq("corp_id", CorpContextHolder.getCorpId());
            queryWrapper.in("channel_id",channelId);
            queryWrapper.eq("employee_id",r.get("employee_id"));
            Map<String, Object> map = getMap(queryWrapper);

            if (entity != null){
                BeanUtil.copyProperties(entity,vo);
                vo.setEmployeeId(entity.getId());
                vo.setAllAddContact(map == null ? 0 : Integer.parseInt(map.get("allAddContact").toString()));
                vo.setNewAddContact(Integer.valueOf(r.get("newAddContact").toString()));
                vo.setAllLossContact(Integer.valueOf(r.get("allLossContact").toString()));
                vos.add(vo);
            }
        });
        iPage.setRecords(vos);
        return iPage;
    }

    /**
     * 按员工查看表格-查看详情-分页
     * @param page
     * @param dto
     * @return
     */
    @Override
    public Page<List<ChannelCodeTableDateDetailsVO>> getChannelCodeTableEmployeeDetails(Page page, ChannelCodeTableEmployeeDetailsDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        List<String> channelIds = new LinkedList<>();
        channelId.forEach(c->{
            channelIds.add("channelCodeId-"+c);
        });

        String nowDate = DateTime.now().toDateStr();
        if (dto.getStartTime() == null) dto.setStartTime(nowDate);
        if (dto.getEndTime() == null) dto.setEndTime(nowDate);

        //查询所有客户
        if (dto.getType().equals(1)){
            IPage iPage = workContactEmployeeService.page(page, Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                    .eq(WorkContactEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(WorkContactEmployeeEntity::getState, channelIds)
                    .eq(WorkContactEmployeeEntity::getEmployeeId,dto.getEmployeeId())
                    .le(BaseEntity::getCreateTime, dto.getEndTime() + " 23:59:59"));
            List<WorkContactEmployeeEntity> records = iPage.getRecords();
            List<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                //获取客户信息
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                //获取员工信息
                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                //获取渠道活码信息
                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                //获取标签信息
                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                //获取当前客户与员工聊天信息
                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());


                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(vos);
            subPage.setPages(iPage.getPages());
            subPage.setTotal(iPage.getTotal());
            subPage.setCurrent(iPage.getCurrent());
            subPage.setSize(iPage.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else if (dto.getType().equals(2)){
            IPage iPage = workContactEmployeeService.page(page, Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                    .eq(WorkContactEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(WorkContactEmployeeEntity::getState, channelIds)
                    .eq(WorkContactEmployeeEntity::getEmployeeId,dto.getEmployeeId())
                    .ge(BaseEntity::getCreateTime, dto.getStartTime() + " 00:00:00")
                    .le(BaseEntity::getCreateTime, dto.getEndTime() + " 23:59:59"));
            List<WorkContactEmployeeEntity> records = iPage.getRecords();
            LinkedList<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(vos);
            subPage.setPages(iPage.getPages());
            subPage.setTotal(iPage.getTotal());
            subPage.setCurrent(iPage.getCurrent());
            subPage.setSize(iPage.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else if (dto.getType().equals(3)){
            List<WorkContactEmployeeEntity> lossContact = workContactEmployeeService.getAllLossContactByEmployee(dto.getEndTime() + " 23:59:59", channelIds,dto.getEmployeeId());
            List<ChannelCodeTableDateDetailsVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            lossContact.forEach(r->{
                ChannelCodeTableDateDetailsVO vo = new ChannelCodeTableDateDetailsVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());


                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vo.setStatus(2);
                vo.setStatusMsg(ChannelCodeStatusEnum.getTypeByCode(vo.getStatus()));
                vos.add(vo);
            });
            List<ChannelCodeTableDateDetailsVO> collect = vos.stream().distinct().collect(Collectors.toList());
            collect.sort(Comparator.comparing(ChannelCodeTableDateDetailsVO::getCreateTime).reversed());

            Page<ChannelCodeTableDateDetailsVO> split = PageUtil.split(collect, (int) page.getCurrent(), (int) page.getSize());
            Map<String, Object> map = new HashMap<>();
            map.put("nowTime",DateTime.now().toDateStr());
            SubPage subPage = new SubPage();
            subPage.setRecords(split.getRecords());
            subPage.setPages(split.getPages());
            subPage.setTotal(split.getTotal());
            subPage.setCurrent(split.getCurrent());
            subPage.setSize(split.getSize());
            subPage.setExtraProps(map);
            return subPage;
        }else {
            HashMap<String, Object> map = new HashMap<>();
            SubPage subPage = new SubPage();
            subPage.setExtraProps(map);
            map.put("nowTime", DateTime.now().toDateStr());
            return subPage;
        }
    }

    /**
     * 按日期查看表格-导出Excel
     * @param dto
     * @param response
     * @param out
     */
    @Override
    public void getChannelCodeTableExcel(ChannelCodeTableDateDTO dto,HttpServletResponse response, OutputStream out) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("create_time,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
        wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
        if (dto.getEmployeeId()!=null){
            wrapper.eq("employee_id",dto.getEmployeeId());
        }
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        wrapper.in("channel_id",channelId);
        wrapper.groupBy("create_time");
        wrapper.orderByDesc("create_time");
        List<Map<String, Object>> maps = listMaps(wrapper);
        List<ChannelCodeTableDateExcelVO> vos = new LinkedList<>();

        List<DateTime> list = DateHastListUtil.getDetHashList(dto.getStartTime(), dto.getEndTime());
        list.forEach(l->{
            ChannelCodeTableDateExcelVO vo = new ChannelCodeTableDateExcelVO();
            vo.setCreateTime(DateUtil.formatDate(l));
            vo.setNewAddContact(0);
            vo.setNewLossContact(0);
            vo.setAllAddContact(0);
            maps.forEach(m->{
                DateTime createTime = DateTime.of(m.get("create_time").toString(), "yyyy-MM-dd");
                if (createTime.getTime() == l.getTime()){
                    vo.setNewAddContact(Integer.valueOf(m.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(m.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(m.get("allAddContact").toString()));
                }
            });
            vos.add(vo);
        });

        vos.sort(Comparator.comparing(ChannelCodeTableDateExcelVO::getCreateTime).reversed());
        excelByTableDate(vos,response,out);
    }

    /**
     * 按员工查看表格-导出Excel
     * @param dto
     * @param response
     * @param out
     */
    @Override
    public void getChannelCodeTableEmployeeExcel(ChannelCodeTableEmployeeDTO dto, HttpServletResponse response, OutputStream out) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
        wrapper.select("employee_id,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
        wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
        wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
        if (dto.getEmployeeId() != null){
            wrapper.eq("employee_id",dto.getEmployeeId());
        }
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        wrapper.in("channel_id",channelId);
        wrapper.groupBy("employee_id");
        wrapper.orderByDesc("employee_id");
        List<Map<String, Object>> records = listMaps(wrapper);
        List<ChannelCodeTableEmployeeExcelVO> vos = new LinkedList<>();
        records.forEach(r->{
            ChannelCodeTableEmployeeExcelVO vo = new ChannelCodeTableEmployeeExcelVO();
            WorkEmployeeEntity entity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .eq(WorkEmployeeEntity::getId, r.get("employee_id")));
            BeanUtil.copyProperties(entity,vo);
            vo.setAllAddContact(Integer.valueOf(r.get("allAddContact").toString()));
            vo.setNewAddContact(Integer.valueOf(r.get("newAddContact").toString()));
            vo.setAllLossContact(Integer.valueOf(r.get("allLossContact").toString()));
            vos.add(vo);
        });
        excelByTableEmployeeDate(vos,response,out);
    }

    /**
     * 按员工查看表格-查看详情-导出Excel
     * @param response
     * @param out
     * @param dto
     */
    @Override
    public void getChannelCodeTableEmployeeDetailsExcel(HttpServletResponse response, OutputStream out, ChannelCodeTableEmployeeDetailsDTO dto) {
        List<Integer> channel = new LinkedList<>();
        if (dto.getChannelId() != null&&!dto.getChannelId().isEmpty()){
            channel.addAll(dto.getChannelId());
        }
        if (dto.getGroupId() != null&&!dto.getGroupId().isEmpty()){
            List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                    .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(ChannelCodeEntity::getGroupId, dto.getGroupId()));
            entities.forEach(e->{
                channel.add(e.getId());
            });
        }
        List<Integer> channelId = channel.stream().distinct().collect(Collectors.toList());

        List<String> channelIds = new LinkedList<>();
        channelId.forEach(c->{
            channelIds.add("channelCodeId-"+c);
        });
        if (dto.getType().equals(1)){
            List<WorkContactEmployeeEntity> records = workContactEmployeeService.list(Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                    .eq(WorkContactEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .eq(WorkContactEmployeeEntity::getEmployeeId,dto.getEmployeeId())
                    .in(WorkContactEmployeeEntity::getState, channelIds)
                    .le(BaseEntity::getCreateTime, dto.getEndTime() + " 23:59:59"));
            LinkedList<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );
                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(r.getStatus()));
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,vos);
        }else if (dto.getType().equals(2)){
            List<WorkContactEmployeeEntity> records = workContactEmployeeService.list(Wrappers.<WorkContactEmployeeEntity>lambdaQuery()
                    .eq(WorkContactEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                    .in(WorkContactEmployeeEntity::getState, channelIds)
                    .eq(WorkContactEmployeeEntity::getEmployeeId,dto.getEmployeeId())
                    .ge(BaseEntity::getCreateTime, dto.getStartTime() + " 00:00:00")
                    .le(BaseEntity::getCreateTime, dto.getEndTime() + " 23:59:59"));
            LinkedList<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            records.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());

                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(r.getStatus()));
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            vos.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,vos);
        }else{
            List<WorkContactEmployeeEntity> lossContact = workContactEmployeeService.getAllLossContactByEmployee(dto.getEndTime() + " 23:59:59", channelIds,dto.getEmployeeId());
            List<ChannelCodeTableDateDetailsExcelVO> vos = new LinkedList<>();
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            lossContact.forEach(r->{
                ChannelCodeTableDateDetailsExcelVO vo = new ChannelCodeTableDateDetailsExcelVO();
                WorkContactEntity entity = workContactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery().eq(WorkContactEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkContactEntity::getId, r.getContactId()));

                WorkEmployeeEntity employeeEntity = employeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .eq(WorkEmployeeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(WorkEmployeeEntity::getId, r.getEmployeeId()));

                BeanUtil.copyProperties(r,vo);
                BeanUtil.copyProperties(entity,vo);

                ChannelCodeEntity codeEntity = channelCodeService.getChannelCodeOne(Integer.valueOf(r.getState().split("-")[1]), CorpContextHolder.getCorpId());


                List<WorkContactTagPivotEntity> tagPivotEntityList = workContactTagPivotService.list(Wrappers.<WorkContactTagPivotEntity>lambdaQuery()
                        .eq(WorkContactTagPivotEntity::getContactId, r.getContactId())
                        .eq(WorkContactTagPivotEntity::getEmployeeId, r.getEmployeeId()));

                LinkedList<String> tagsList = new LinkedList<>();
                tagPivotEntityList.forEach(tag->{
                    WorkContactTagEntity tagEntity = workContactTagService.getOne(Wrappers.<WorkContactTagEntity>lambdaQuery()
                            .eq(WorkContactTagEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(WorkContactTagEntity::getId, tag.getContactTagId()));
                    if (tagEntity != null){
                        tagsList.add(tagEntity.getName());
                    }
                });

                WorkMsgEntity workMsgEntity = workMsgMapper.countTime(employeeEntity.getWxUserId(), entity.getWxExternalUserid(), CorpContextHolder.getCorpId());
                vo.setLastTime(workMsgEntity == null ? "" : DateUtils.formatS1(workMsgEntity.getMsgTime()) );

                vo.setCustomerScoring(0);
                vo.setStatus(ChannelCodeStatusEnum.getTypeByCode(2));
                vo.setTagsList(tagsList.stream().distinct().collect(Collectors.toList()));
                vo.setContactName(entity.getName());
                vo.setEmployeeName(employeeEntity.getName());
                vo.setCreateTime(pattern.format(r.getCreateTime()));
                vo.setChannel("通过渠道活码【"+codeEntity.getName()+"】加入");
                vos.add(vo);
            });
            List<ChannelCodeTableDateDetailsExcelVO> collect = vos.stream().distinct().collect(Collectors.toList());
            collect.sort(Comparator.comparing(ChannelCodeTableDateDetailsExcelVO::getCreateTime).reversed());
            getChannelCodeTableDateDetailsExcel(response,out,collect);
        }
    }

    /**
     * 渠道活码对比数据基础信息
     * @param dto
     * @return
     */
    @Override
    public List<ChannelCodeContrastDetailsVO> getChannelCodeContrastDetails(ChannelCodeContrastDetailsDTO dto) {
        List<ChannelCodeContrastDetailsVO> vos = new LinkedList<>();
        if (dto.getGroupId() != null){
            dto.getGroupId().forEach(group->{
                ChannelCodeContrastDetailsVO vo = new ChannelCodeContrastDetailsVO();
                ChannelCodeGroupEntity entity = channelCodeGroupService.getOne(Wrappers.<ChannelCodeGroupEntity>lambdaQuery()
                        .eq(ChannelCodeGroupEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeGroupEntity::getId, group));
                List<Integer> channelId = new LinkedList<>();
                List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                        .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeEntity::getGroupId, group));
                entities.forEach(e->{
                    channelId.add(e.getId());
                });
                QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                wrapper.select("sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                wrapper.ge("create_time",DateUtil.beginOfDay(new Date()));
                wrapper.le("create_time",DateUtil.endOfDay(new Date()));
                wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                wrapper.in("channel_id",channelId);
                Map<String, Object> map = getMap(wrapper);
                if (map != null){
                    vo.setAllLossContact(Integer.valueOf(map.get("allLossContact").toString()));
                    vo.setNewAddContact(Integer.valueOf(map.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(map.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(map.get("allAddContact").toString()));
                }else {
                    vo.setAllLossContact(0);
                    vo.setNewAddContact(0);
                    vo.setNewLossContact(0);
                    vo.setAllAddContact(0);
                }
                vo.setName(entity.getName());
                vo.setType(1);
                vo.setId(group);
                vos.add(vo);
            });
        }

        if (dto.getChannelId() != null){
            dto.getChannelId().forEach(channel->{
                ChannelCodeContrastDetailsVO vo = new ChannelCodeContrastDetailsVO();
                ChannelCodeEntity entity = channelCodeService.getOne(Wrappers.<ChannelCodeEntity>lambdaQuery()
                        .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeEntity::getId, channel));
                QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                wrapper.select("sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                wrapper.ge("create_time",DateUtil.beginOfDay(new Date()));
                wrapper.le("create_time",DateUtil.endOfDay(new Date()));
                wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                wrapper.eq("channel_id",channel);
                Map<String, Object> map = getMap(wrapper);
                if (map != null){
                    vo.setAllLossContact(Integer.valueOf(map.get("allLossContact").toString()));
                    vo.setNewAddContact(Integer.valueOf(map.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(map.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(map.get("allAddContact").toString()));
                }else {
                    vo.setAllLossContact(0);
                    vo.setNewAddContact(0);
                    vo.setNewLossContact(0);
                    vo.setAllAddContact(0);
                }
                vo.setName(entity.getName());
                vo.setType(2);
                vo.setId(channel);
                vos.add(vo);
            });
        }
        return vos;
    }

    /**
     * 渠道活码对比数据基础信息-导出Excel
     * @param response
     * @param out
     * @param dto
     */
    @Override
    public void getChannelCodeContrastDetailsExcel(HttpServletResponse response, OutputStream out, ChannelCodeContrastDetailsDTO dto) {
        List<ChannelCodeContrastDetailsExcelVO> vos = new LinkedList<>();
        if (dto.getGroupId() != null){
            dto.getGroupId().forEach(group->{
                ChannelCodeContrastDetailsExcelVO vo = new ChannelCodeContrastDetailsExcelVO();
                ChannelCodeGroupEntity entity = channelCodeGroupService.getOne(Wrappers.<ChannelCodeGroupEntity>lambdaQuery()
                        .eq(ChannelCodeGroupEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeGroupEntity::getId, group));
                List<Integer> channelId = new LinkedList<>();
                List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                        .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeEntity::getGroupId, group));
                entities.forEach(e->{
                    channelId.add(e.getId());
                });
                QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                wrapper.select("sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                wrapper.ge("create_time",DateUtil.beginOfDay(new Date()));
                wrapper.le("create_time",DateUtil.endOfDay(new Date()));
                wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                wrapper.in("channel_id",channelId);
                Map<String, Object> map = getMap(wrapper);
                if (map != null){
                    vo.setAllLossContact(Integer.valueOf(map.get("allLossContact").toString()));
                    vo.setNewAddContact(Integer.valueOf(map.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(map.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(map.get("allAddContact").toString()));
                }else {
                    vo.setAllLossContact(0);
                    vo.setNewAddContact(0);
                    vo.setNewLossContact(0);
                    vo.setAllAddContact(0);
                }
                vo.setName(entity.getName());
                vo.setType("渠道分组");
                vos.add(vo);
            });
        }

        if (dto.getChannelId() != null){
            dto.getChannelId().forEach(channel->{
                ChannelCodeContrastDetailsExcelVO vo = new ChannelCodeContrastDetailsExcelVO();
                ChannelCodeEntity entity = channelCodeService.getOne(Wrappers.<ChannelCodeEntity>lambdaQuery()
                        .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                        .eq(ChannelCodeEntity::getId, channel));
                QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                wrapper.select("sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                wrapper.ge("create_time",DateUtil.beginOfDay(new Date()));
                wrapper.le("create_time",DateUtil.endOfDay(new Date()));
                wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                wrapper.eq("channel_id",channel);
                Map<String, Object> map = getMap(wrapper);
                if (map != null){
                    vo.setAllLossContact(Integer.valueOf(map.get("allLossContact").toString()));
                    vo.setNewAddContact(Integer.valueOf(map.get("newAddContact").toString()));
                    vo.setNewLossContact(Integer.valueOf(map.get("newLossContact").toString()));
                    vo.setAllAddContact(Integer.valueOf(map.get("allAddContact").toString()));
                }else {
                    vo.setAllLossContact(0);
                    vo.setNewAddContact(0);
                    vo.setNewLossContact(0);
                    vo.setAllAddContact(0);
                }
                vo.setName(entity.getName());
                vo.setType("渠道码");
                vos.add(vo);
            });
        }
        getChannelCodeContrastDetailsExcel(vos,response,out);
    }

    @Override
    public List<ChannelCodeContrastLineChartVO> getChannelCodeContrastLineChart(ChannelCodeContrastLineChartDTO dto) {
        List<DateTime> list = DateHastListUtil.getDetHashList(dto.getStartTime(), dto.getEndTime());
        if (dto.getType().equals(1)){
            List<ChannelCodeContrastLineChartVO> vos = new LinkedList<>();
            list.forEach(l->{

            });
            if (dto.getGroupId() != null){
                dto.getGroupId().forEach(group->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeGroupEntity entity = channelCodeGroupService.getOne(Wrappers.<ChannelCodeGroupEntity>lambdaQuery()
                            .eq(ChannelCodeGroupEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeGroupEntity::getId, group));
                    List<Integer> channelId = new LinkedList<>();
                    List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getGroupId, group));
                    entities.forEach(e->{
                        channelId.add(e.getId());
                    });
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.in("channel_id",channelId);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            if (dto.getChannelId() != null){
                dto.getChannelId().forEach(channel->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeEntity entity = channelCodeService.getOne(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getId, channel));
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.eq("channel_id",channel);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            return vos;
        }else if (dto.getType().equals(2)){
            List<ChannelCodeContrastLineChartVO> vos = new LinkedList<>();
            if (dto.getGroupId() != null){
                dto.getGroupId().forEach(group->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeGroupEntity entity = channelCodeGroupService.getOne(Wrappers.<ChannelCodeGroupEntity>lambdaQuery()
                            .eq(ChannelCodeGroupEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeGroupEntity::getId, group));
                    List<Integer> channelId = new LinkedList<>();
                    List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getGroupId, group));
                    entities.forEach(e->{
                        channelId.add(e.getId());
                    });
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.in("channel_id",channelId);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            if (dto.getChannelId() != null){
                dto.getChannelId().forEach(channel->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeEntity entity = channelCodeService.getOne(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getId, channel));
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.eq("channel_id",channel);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            return vos;
        }else if (dto.getType().equals(3)){
            List<ChannelCodeContrastLineChartVO> vos = new LinkedList<>();
            if (dto.getGroupId() != null){
                dto.getGroupId().forEach(group->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeGroupEntity entity = channelCodeGroupService.getOne(Wrappers.<ChannelCodeGroupEntity>lambdaQuery()
                            .eq(ChannelCodeGroupEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeGroupEntity::getId, group));
                    List<Integer> channelId = new LinkedList<>();
                    List<ChannelCodeEntity> entities = channelCodeService.list(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getGroupId, group));
                    entities.forEach(e->{
                        channelId.add(e.getId());
                    });
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.in("channel_id",channelId);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            if (dto.getChannelId() != null){
                dto.getChannelId().forEach(channel->{
                    ChannelCodeContrastLineChartVO vo = new ChannelCodeContrastLineChartVO();
                    ChannelCodeEntity entity = channelCodeService.getOne(Wrappers.<ChannelCodeEntity>lambdaQuery()
                            .eq(ChannelCodeEntity::getCorpId,  CorpContextHolder.getCorpId())
                            .eq(ChannelCodeEntity::getId, channel));
                    QueryWrapper<ChannelCodeContactStatisticsEntity> wrapper = new QueryWrapper<>();
                    wrapper.select("create_time as createTime,sum(all_add_contact) as allAddContact,sum(new_loss_contact) as newLossContact , sum(all_loss_contact) as allLossContact,sum(new_add_contact) as newAddContact");
                    wrapper.ge("create_time",dto.getStartTime()+" 00:00:00");
                    wrapper.le("create_time",dto.getEndTime()+" 23:59:59");
                    wrapper.eq("corp_id", CorpContextHolder.getCorpId());
                    wrapper.eq("channel_id",channel);
                    if (dto.getEmployeeId() != null){
                        wrapper.eq("employee_id",dto.getEmployeeId());
                    }
                    wrapper.groupBy("create_time");
                    List<Map<String, Object>> mapList = listMaps(wrapper);
                    LinkedList<ChannelCodeContrastLineChartDate> chartDates = new LinkedList<>();
                    list.forEach(l->{
                        ChannelCodeContrastLineChartDate date = new ChannelCodeContrastLineChartDate();
                        date.setDate(DateUtil.formatDate(l));
                        date.setCount(0);
                        mapList.forEach(m->{
                            DateTime createTime = DateUtil.parseDate(m.get("createTime").toString());
                            if (createTime.getTime() == l.getTime()){
                                date.setCount(Integer.valueOf(m.get("allAddContact").toString()));
                            }
                        });
                        chartDates.add(date);
                    });
                    vo.setName(entity.getName());
                    vo.setDataList(chartDates);
                    vo.setType(dto.getType());
                    vos.add(vo);
                });
            }
            return vos;
        }else {
            return new LinkedList<>();
        }
    }

    /**
     * 渠道活码对比数据基础信息-导出Excel-私有方法
     * @param vos
     * @param response
     * @param out
     */
    private void getChannelCodeContrastDetailsExcel(List<ChannelCodeContrastDetailsExcelVO> vos, HttpServletResponse response, OutputStream out){
        ArrayList<ChannelCodeContrastDetailsExcelVO> rows = CollUtil.newArrayList(vos);
        if (rows.isEmpty()){
            ChannelCodeContrastDetailsExcelVO vo = new ChannelCodeContrastDetailsExcelVO();
            rows.add(vo);
        }
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);



        //自定义标题别名
        writer.addHeaderAlias("name", "渠道码（组）名称");
        writer.addHeaderAlias("allAddContact", "总客户数");
        writer.addHeaderAlias("newAddContact", "今日新增客户数");
        writer.addHeaderAlias("newLossContact", "今日流失客户数");
        writer.addHeaderAlias("allAddContact", "总客户数");
        writer.addHeaderAlias("allLossContact", "总流失客户数");
        writer.addHeaderAlias("type", "类型 1为渠道分组 2为渠道码");


        writer.autoSizeColumnAll();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=table-date.xlsx");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }

    /**
     * 按日期查看表格-导出Excel-私有方法
     * @param vos
     * @param response
     * @param out
     */
    private void excelByTableDate(List<ChannelCodeTableDateExcelVO> vos, HttpServletResponse response, OutputStream out){
        ArrayList<ChannelCodeTableDateExcelVO> rows = CollUtil.newArrayList(vos);
        if (rows.isEmpty()){
            ChannelCodeTableDateExcelVO vo = new ChannelCodeTableDateExcelVO();
            rows.add(vo);
        }
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);



        //自定义标题别名
        writer.addHeaderAlias("createTime", "日期");
        writer.addHeaderAlias("allAddContact", "总客户数");
        writer.addHeaderAlias("newAddContact", "今日新增客户数");
        writer.addHeaderAlias("newLossContact", "今日流失客户数");


        writer.autoSizeColumnAll();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=table-date.xlsx");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }

    /**
     * 按员工查看表格-导出Excel-私有方法
     * @param vos
     * @param response
     * @param out
     */
    private void excelByTableEmployeeDate(List<ChannelCodeTableEmployeeExcelVO> vos, HttpServletResponse response, OutputStream out){
        ArrayList<ChannelCodeTableEmployeeExcelVO> rows = CollUtil.newArrayList(vos);
        if (rows.isEmpty()){
            ChannelCodeTableEmployeeExcelVO vo = new ChannelCodeTableEmployeeExcelVO();
            rows.add(vo);
        }
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);



        //自定义标题别名
        writer.addHeaderAlias("name", "姓名");
        writer.addHeaderAlias("allAddContact", "总客户数");
        writer.addHeaderAlias("newAddContact", "今日新增客户数");
        writer.addHeaderAlias("allLossContact", "流失客户数");


        writer.autoSizeColumnAll();

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=table-date-employee.xlsx");

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }
}
